package reflectdemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectClassDemo {

    public static void reflectNewInstance() {
        Class<?> stu1;
        try {
            //反射机制中获取 Class 对象的三种方式之一
            stu1 = Class.forName("reflectdemo.Student");
            // 反射机制中通过 Class 对象创建类实例的典型用法
            Student student = (Student)stu1.newInstance();
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void reflectPrivateConstructor() {
        Class<?> stu1;
        try {
            stu1 = Class.forName("reflectdemo.Student");
            //反射机制中获取特定构造方法对象的关键步骤
            //使用通配符 <?> 的主要目的是 表示未知的构造方法类型，同时保证类型安全
            Constructor<?> constructor = stu1.getDeclaredConstructor(String.class, int.class);

            constructor.setAccessible(true);

            //通过反射动态创建一个 Student 类的实例，并调用其构造方法传入参数。
            //需要强转的原因 newInstance() 的返回类型是 Object
            Student student = (Student)constructor.newInstance("zhangsan",18);

            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void reflectPrivateField() {
        Class<?> stu1;
        try {
            stu1 = Class.forName("reflectdemo.Student");

            Field field = stu1.getDeclaredField("name");
            field.setAccessible(true);

            Student student = (Student)stu1.newInstance();
            //1.修改哪个对象的字段 2.修改的值是什么
            field.set(student,"lisi");

            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void reflectPrivateMethod() {
        Class<?> stu1;
        try {
            stu1 = Class.forName("reflectdemo.Student");

            Method method = stu1.getDeclaredMethod("function", String.class);

            Student student = (Student)stu1.newInstance();

            method.setAccessible(true);

            method.invoke(student,"我试着传一个参数");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        //reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();

        reflectPrivateMethod();
    }
}
